package base.jdk8_demo.lambda.demo10;

import base.jdk8_demo.lambda.demo02.Emp;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * jdk8 实现 Map遍历, 以及 Map List 互转
 */
public class TransformCollection {
    private Map<String, Integer> map = new HashMap<>();
    {
        map.put("zs", 18);
        map.put("ls", 19);
        map.put("ww", 20);
    }

    /**
     * jdk8开始提供了 对Map数据类型的 forEach 遍历方法
     */
    @Test
    public void testMapForEach(){
        map.forEach((k,v) -> System.out.println(k + "=" +v));
    }

    /**
     * Map 转 List
     */
    @Test
    public void testMap2List(){
        List<Emp> collect = map.entrySet()  //提取 Map.Entry 的 Set集合
                .stream() //转换成流
                .map(e -> new Emp(e.getKey(), e.getValue())) // map reduce
                .collect(Collectors.toList());

//        Set<Map.Entry<String, Integer>> set = map.entrySet();
//        System.out.println(set);//[ww=20, ls=19, zs=18]
//        Stream<Map.Entry<String, Integer>> entryStream = set.stream();
//        Stream<Emp> empStream = entryStream.map(entry -> new Emp(entry.getKey(), entry.getValue()));
//        collect = empStream.collect(Collectors.toList());

        // 方式一:
//        for (Emp emp : collect) {
//            System.out.println(emp);
//        }
        // 方式二: jdk1.8 开始
        collect.forEach(e -> System.out.println(e));
    }

    /**
     * List 转 Map
     */
    @Test
    public void testList2Map(){
        List<Emp> list = Arrays.asList(
                new Emp(1,"zs", 18),
                new Emp(2,"ls", 19),
                new Emp(3,"ww", 20)
        );

        /**
         * 转换成 Stream
         * collect 进行归集, 需要个归集器 Collector
         * Collectors.toMap 产生个归集器
        */
        Map<String, Integer> map = list.stream()
                .collect(Collectors.toMap((emp)-> emp.getName(), Emp::getAge));

        System.out.println(map);//{ww=20, ls=19, zs=18}
        System.out.println("----------111------------");

        // 收集对象本身
        Map<Integer, Emp> self = list.stream()
                .collect(Collectors.toMap(Emp::getId, emp -> emp));
        System.out.println(self);
        System.out.println("---------222-----------");
        // 还可以用Function接口中的一个默认方法Function.identity(),返回对象本身
        self = list.stream()
                .collect(Collectors.toMap(Emp::getId, Function.identity()));//Function::identity???
        System.out.println(self);
        System.out.println("---------333-----------");

        // 故意给list中添加一个重复Emp.name
        list = Arrays.asList(
                new Emp(1,"zs", 18),
                new Emp(2,"ls", 19),
                new Emp(3,"ww", 20),
                new Emp(4,"ww", 21)
        );
        // key重复的情况，key有可能重复，会抛出异常：java.lang.illegalStateException:Duplicate key.
        // 这时候就要在toMap方法第三个入参中指定当前Key冲突时Value的选择，这里选择的是第二个Value覆盖第一个Value
        Map<String, Emp> map2 = list.stream()
                .collect(Collectors.toMap(Emp::getName, Function.identity(), (emp1, emp2) -> emp2));
        // 下面演示一个重复Key后，新Value自定义组装逻辑如下
//                .collect(Collectors.toMap(
//                            Emp::getName,
//                            Function.identity(),
//                            (emp1, emp2) -> new Emp(emp1.getId(), emp1.getName()+emp2.getName(), emp2.getAge())
//                        )
//                );
        System.out.println(map2);

        // 根据一个字段或者属性分组（这里演示的是年龄）也可以直接用groupingby方法
        Map<Integer, List<Emp>> collect = list.stream().limit(10).collect(Collectors.groupingBy(Emp::getAge));
        System.out.println(collect);

    }

}
